import logging
import uuid
import os
import asyncio
import time
from functools import partial

from fastapi import APIRouter, File, Depends, UploadFile, Body
from fastapi.exceptions import HTTPException

from settings import WORK_DIR, configs
from scanner import ConScanner, update_scanner_config, get_scanner_config, ScannerConfig
from shared import get_scanner

router = APIRouter()
logger = logging.getLogger('audit')


@router.post('/scan')
async def scan_file(
        file: UploadFile = File(...),
        scanner: ConScanner = Depends(get_scanner),
):
    """
    通过瑞星SDK提供在线的查毒服务，**只查不杀**
    ## 输入参数说明： ##
    - **file**：待查毒的文件，需要通过multipart/form-data提交文件，*最大文件大小：20M*
    ## 返回内容： ##
    ```json
    {
        "overtime": false,
        "result": "Trojan.Emotet!1.BE18 (classic)"
    }
    ```
    ## 输出参数说明： ##
    - **overtime**: 查毒是否超时
    - **result**: null：没有正常解析查毒结果，""：不报毒，非空：报毒的病毒名
    """
    if not scanner:
        raise HTTPException(status_code=500, detail='引擎未正常初始化')

    temp_dir = WORK_DIR / 'temp_files'
    os.makedirs(temp_dir, exist_ok=True)
    f_dest = temp_dir / '{}_{}'.format(file.filename, uuid.uuid4())
    with open(f_dest, 'wb') as fp:
        # for buffer in iter(partial(file.file.read, 64 * 1024), b''):
        #     fp.write(buffer)
        fp.write(await file.read())

    overtime, result = await asyncio.get_running_loop().run_in_executor(None, partial(scanner.scan_file, f_dest))
    os.unlink(f_dest)
    return {
        'overtime': overtime,
        'result': result
    }


@router.post('/restart')
async def restart_scanner(
        scan_params: str = Body(..., title='SDK扫描器参数'),
        force: bool = Body(True, title='是否强制重启SDK扫描器'),
        scanner: ConScanner = Depends(get_scanner)
):
    """
    重新启动后台SDK扫描器，使用传入的扫描器参数重启扫描器
    ## 输入参数说明： ##
    - **scan_params**：SDK扫描器参数，例如：-cav=1 -product=rising -rdm.vba=1
    - **force**：是否强制重启扫描器，如果为False则比对扫描器参数，只有扫描器参数变化了才重启；如果为True则直接重启
    ## 返回内容： ##
        无
    """
    if force:
        update_scanner_config(ScannerConfig(int(time.time()), scan_params, force))
        await asyncio.get_running_loop().run_in_executor(None, scanner.check_scanner_cfg)
    else:
        cfg = get_scanner_config()
        if cfg.scan_params != scan_params:
            update_scanner_config(ScannerConfig(int(time.time()), scan_params, force))
            await asyncio.get_running_loop().run_in_executor(None, scanner.check_scanner_cfg)


@router.post('/upgrade')
async def upgrade_lib(
        scanner: ConScanner = Depends(get_scanner)
):
    """
    升级病毒库，需要连接瑞星升级服务器进行在线升级
    ## 输入参数说明： ##
        无
    ## 返回内容： ##
        无
    """
    loop = asyncio.get_running_loop()
    success, msg = await loop.run_in_executor(None, partial(scanner.upgrade_lib, configs['lib_name']))
    if not success:
        raise HTTPException(status_code=500, detail=msg)
    cfg = get_scanner_config()
    update_scanner_config(ScannerConfig(int(time.time()), cfg.scan_params if cfg else configs['scan_params'], True))
    await loop.run_in_executor(None, scanner.check_scanner_cfg)
